!-------------------------------------------------------------LICENSE--------------------------------------------------------------!
!                                                                                                                                  !
!The MAP code is written in Fortran language for magnetohydrodynamics (MHD) calculation with the adaptive mesh refinement (AMR)    !
!and Message Passing Interface (MPI) parallelization.                                                                              !
!                                                                                                                                  !
!Copyright (C) 2012                                                                                                                !
!Ronglin Jiang                                                                                                                     !
!rljiang@ssc.net.cn                                                                                                                !
!585 Guoshoujing Road. Pudong, Shanghai, P.R.C. 201203                                                                             !
!                                                                                                                                  !
!This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License         !
!as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.             !
!                                                                                                                                  !
!This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of    !
!MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.                        !
!                                                                                                                                  !
!You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software     !
!Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.                                                   !
!                                                                                                                                  !
!-------------------------------------------------------------LICENSE--------------------------------------------------------------!

!==================================================================================================================================|
subroutine neigh_statistics (base)
!==================================================================================================================================|

   use parameters
   use block_define
   implicit none

   type(block), pointer, intent(in) :: base

   integer(4) :: i_neigh, j_neigh, i_cpu, i_block, j_block, i_neigh_x
   integer(4) :: child_cpu_id_p1, neigh_cpu_id_p1, neigh_index
   integer(4), dimension(cpu_number) :: n_neighs_exchange_send_x, n_neighs_exchange_send_y, n_neighs_exchange_send_fix_y
   integer(4), dimension(cpu_number) :: n_neighs_shareblock_send_x, n_neighs_shareblock_send_y
   integer(4), dimension(cpu_number) :: n_neighs_reflux_send_x, n_neighs_reflux_send_y
   
   integer(4) :: reflux_size_x_tmp
   integer(4) :: reflux_size_y_tmp
   integer(4) :: shareblock_size_x_tmp
   integer(4) :: shareblock_size_y_tmp
   integer(4) :: exchange_size_x_tmp
   integer(4) :: exchange_size_y_tmp
   integer(4) :: exchange_size_fix_y_tmp

   integer(4), dimension(:, :, :), allocatable :: neighs_reflux_info_send_x_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_reflux_info_send_y_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_reflux_info_recv_x_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_reflux_info_recv_y_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_shareblock_info_send_x_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_shareblock_info_send_y_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_shareblock_info_recv_x_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_shareblock_info_recv_y_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_exchange_info_send_x_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_exchange_info_send_y_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_exchange_info_recv_x_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_exchange_info_recv_y_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_exchange_info_send_fix_y_tmp
   integer(4), dimension(:, :, :), allocatable :: neighs_exchange_info_recv_fix_y_tmp

   logical(4) :: child_send_flag(cpu_number)
   type(block), pointer :: current, neigh, child, neigh_x, neigh_c

!----------------------------------------------------------------------------------------------------------------------------------|
   do i_cpu = 1, cpu_number
      n_neighs_reflux_send_x(i_cpu) = 0
      n_neighs_reflux_send_y(i_cpu) = 0
      n_neighs_shareblock_send_x(i_cpu) = 0
      n_neighs_shareblock_send_y(i_cpu) = 0
      n_neighs_exchange_send_x(i_cpu) = 0
      n_neighs_exchange_send_y(i_cpu) = 0
      n_neighs_exchange_send_fix_y(i_cpu) = 0
   enddo

!----------------------------------------------------------------------------------------------------------------------------------|
!  update cpu_number_neigh
!----------------------------------------------------------------------------------------------------------------------------------|
!   neigh_flag = .false.
!   cpu_number_neigh_tmp = 0
!   current => base%next
!   do while (current%lv .ne. 0)
!      j_neigh = 0
!      do i_neigh = -1, 1, 2
!         neigh => current%neigh(i_neigh, j_neigh)%pblock
!         if (.not. associated(neigh)) cycle
!         if (neigh%lv .lt. 0) cycle
!         if (neigh%cpu_id .ne. cpu_id .and. .not. neigh_flag(neigh%cpu_id + 1)) then
!            cpu_number_neigh_tmp = cpu_number_neigh_tmp + 1
!            neigh_flag(neigh%cpu_id + 1) = .true.
!         endif
!      enddo
!      i_neigh = 0
!      do j_neigh = -1, 1, 2
!         neigh => current%neigh(i_neigh, j_neigh)%pblock
!         if (.not. associated(neigh)) cycle
!         if (neigh%lv .lt. 0) cycle
!         if (neigh%cpu_id .ne. cpu_id .and. .not. neigh_flag(neigh%cpu_id + 1)) then
!            cpu_number_neigh_tmp = cpu_number_neigh_tmp + 1
!            neigh_flag(neigh%cpu_id + 1) = .true.
!         endif
!      enddo
!      current => current%next
!   enddo

!   if (cpu_number_neigh .ne. cpu_number_neigh_tmp) then
!      cpu_number_neigh = cpu_number_neigh_tmp

   if (allocated(neighs_reflux_send_x)) deallocate(neighs_reflux_send_x)
   if (allocated(neighs_reflux_send_y)) deallocate(neighs_reflux_send_y)
   if (allocated(neighs_reflux_recv_x)) deallocate(neighs_reflux_recv_x)
   if (allocated(neighs_reflux_recv_y)) deallocate(neighs_reflux_recv_y)

   if (allocated(neighs_shareblock_send_x)) deallocate(neighs_shareblock_send_x)
   if (allocated(neighs_shareblock_send_y)) deallocate(neighs_shareblock_send_y)
   if (allocated(neighs_shareblock_recv_x)) deallocate(neighs_shareblock_recv_x)
   if (allocated(neighs_shareblock_recv_y)) deallocate(neighs_shareblock_recv_y)

   if (allocated(neighs_exchange_send_x)) deallocate(neighs_exchange_send_x)
   if (allocated(neighs_exchange_send_y)) deallocate(neighs_exchange_send_y)
   if (allocated(neighs_exchange_recv_x)) deallocate(neighs_exchange_recv_x)
   if (allocated(neighs_exchange_recv_y)) deallocate(neighs_exchange_recv_y)

   if (allocated(neighs_shareblock_send_x_hc)) deallocate(neighs_shareblock_send_x_hc)
   if (allocated(neighs_shareblock_send_y_hc)) deallocate(neighs_shareblock_send_y_hc)
   if (allocated(neighs_shareblock_recv_x_hc)) deallocate(neighs_shareblock_recv_x_hc)
   if (allocated(neighs_shareblock_recv_y_hc)) deallocate(neighs_shareblock_recv_y_hc)

   if (allocated(neighs_exchange_send_x_hc)) deallocate(neighs_exchange_send_x_hc)
   if (allocated(neighs_exchange_send_y_hc)) deallocate(neighs_exchange_send_y_hc)
   if (allocated(neighs_exchange_recv_x_hc)) deallocate(neighs_exchange_recv_x_hc)
   if (allocated(neighs_exchange_recv_y_hc)) deallocate(neighs_exchange_recv_y_hc)

!      allocate(neighs_reflux_send_x(sys, ny_no_bnd, reflux_size_x, cpu_number_neigh))
!      allocate(neighs_reflux_send_y(sys, nx_no_bnd, reflux_size_y, cpu_number_neigh))
!      allocate(neighs_reflux_recv_x(sys, ny_no_bnd, reflux_size_x, cpu_number_neigh))
!      allocate(neighs_reflux_recv_y(sys, nx_no_bnd, reflux_size_y, cpu_number_neigh))

!      allocate(neighs_shareblock_send_x(sys + 2, ng + 1, ny_block, shareblock_size_x, cpu_number_neigh))
!      allocate(neighs_shareblock_send_y(sys + 2, nx_block, ng + 1, shareblock_size_y, cpu_number_neigh))
!      allocate(neighs_shareblock_recv_x(sys + 2, ng + 1, ny_block, shareblock_size_x, cpu_number_neigh))
!      allocate(neighs_shareblock_recv_y(sys + 2, nx_block, ng + 1, shareblock_size_y, cpu_number_neigh))

!      allocate(neighs_exchange_send_x(sys + 2, ng, ny_no_bnd, exchange_size_x, cpu_number_neigh))
!      allocate(neighs_exchange_send_y(sys + 2, nx_block, ng, exchange_size_y, cpu_number_neigh))
!      allocate(neighs_exchange_recv_x(sys + 2, ng, ny_no_bnd, exchange_size_x, cpu_number_neigh))
!      allocate(neighs_exchange_recv_y(sys + 2, nx_block, ng, exchange_size_y, cpu_number_neigh))

!      allocate(neighs_shareblock_send_x_hc(1, ng + 1, ny_block, shareblock_size_x, cpu_number_neigh))
!      allocate(neighs_shareblock_send_y_hc(1, nx_block, ng + 1, shareblock_size_y, cpu_number_neigh))
!      allocate(neighs_shareblock_recv_x_hc(1, ng + 1, ny_block, shareblock_size_x, cpu_number_neigh))
!      allocate(neighs_shareblock_recv_y_hc(1, nx_block, ng + 1, shareblock_size_y, cpu_number_neigh))

!      allocate(neighs_exchange_send_x_hc(1, ng, ny_no_bnd, exchange_size_x, cpu_number_neigh))
!      allocate(neighs_exchange_send_y_hc(1, nx_block, ng, exchange_size_y, cpu_number_neigh))
!      allocate(neighs_exchange_recv_x_hc(1, ng, ny_no_bnd, exchange_size_x, cpu_number_neigh))
!      allocate(neighs_exchange_recv_y_hc(1, nx_block, ng, exchange_size_y, cpu_number_neigh))

   current => base%next
   do while (current%lv .ne. 0)
!----------------------------------------------------------------------------------------------------------------------------------|
!     statistics in x direction
!----------------------------------------------------------------------------------------------------------------------------------|
      j_neigh = 0
      do i_neigh = -1, 1, 2      !  skip current%neigh(0, 0)%pblock
         neigh => current%neigh(i_neigh, j_neigh)%pblock

!----------------------------------------------------------------------------------------------------------------------------------|
!        skip if neigh is physical boundary or inner physical boundary
!----------------------------------------------------------------------------------------------------------------------------------|
         if (.not. associated (neigh)) cycle
         if (neigh%lv .lt. 0) cycle

         neigh_cpu_id_p1 = neigh%cpu_id + 1

!----------------------------------------------------------------------------------------------------------------------------------|
!        collect information of neighbors for sending reflux data in x (different levels)
!----------------------------------------------------------------------------------------------------------------------------------|
         if (current%lv .gt. neigh%lv .and. neigh%cpu_id .ne. cpu_id) then
            n_neighs_reflux_send_x(neigh_cpu_id_p1) = n_neighs_reflux_send_x(neigh_cpu_id_p1) + 1
            neigh_index = n_neighs_reflux_send_x(neigh_cpu_id_p1)
!----------------------------------------------------------------------------------------------------------------------------------|
!           for the case n_neighs_reflux_send_x(neigh_cpu_id_p1) larger than the reflux_size_x
!----------------------------------------------------------------------------------------------------------------------------------|
            if (neigh_index .gt. reflux_size_x) then
               allocate(neighs_reflux_info_send_x_tmp(n_d_l + 1, reflux_size_x, cpu_number))
               allocate(neighs_reflux_info_recv_x_tmp(n_d_l + 1, reflux_size_x, cpu_number))
               reflux_size_x_tmp = reflux_size_x
               neighs_reflux_info_send_x_tmp = neighs_reflux_info_send_x
               neighs_reflux_info_recv_x_tmp = neighs_reflux_info_recv_x
               reflux_size_x = reflux_size_x + ini_block_x * ini_block_y
               deallocate(neighs_reflux_info_send_x)
               deallocate(neighs_reflux_info_recv_x)
               allocate(neighs_reflux_info_send_x(n_d_l + 1, reflux_size_x, cpu_number))
               allocate(neighs_reflux_info_recv_x(n_d_l + 1, reflux_size_x, cpu_number))
               neighs_reflux_info_send_x(:, 1 : reflux_size_x_tmp, :) = neighs_reflux_info_send_x_tmp
               neighs_reflux_info_recv_x(:, 1 : reflux_size_x_tmp, :) = neighs_reflux_info_recv_x_tmp
               deallocate(neighs_reflux_info_send_x_tmp)
               deallocate(neighs_reflux_info_recv_x_tmp)
            endif
            neighs_reflux_info_send_x(1 : n_d_l, neigh_index, neigh_cpu_id_p1) = reshape(current%id, (/ n_d_l /))
            neighs_reflux_info_send_x(n_d_l + 1, neigh_index, neigh_cpu_id_p1) = i_neigh
            cycle
         endif

!----------------------------------------------------------------------------------------------------------------------------------|
!        collect information of neighbors for sending boundary data in x (same levels)
!----------------------------------------------------------------------------------------------------------------------------------|
         if (neigh%cpu_id .ne. cpu_id) then
!            if (.not. neigh%var_allocate_flag) then
!               allocate(neigh%ro(nx_block, ny_block), neigh%mx(nx_block, ny_block), neigh%my(nx_block, ny_block),                  &
!                        neigh%mz(nx_block, ny_block), neigh%bx(nx_block, ny_block), neigh%by(nx_block, ny_block),                  &
!                        neigh%bz(nx_block, ny_block), neigh%en(nx_block, ny_block), neigh%gx(nx_block, ny_block),                  &
!                        neigh%gy(nx_block, ny_block), neigh%po(nx_block, ny_block), neigh%az(nx_block, ny_block))
!               allocate(neigh%fxro_bnd(ny_block, n_neighs), neigh%fxmx_bnd(ny_block, n_neighs),                                    &
!                        neigh%fxmy_bnd(ny_block, n_neighs), neigh%fxmz_bnd(ny_block, n_neighs),                                    &
!                        neigh%fxbx_bnd(ny_block, n_neighs), neigh%fxby_bnd(ny_block, n_neighs),                                    &
!                        neigh%fxbz_bnd(ny_block, n_neighs), neigh%fxen_bnd(ny_block, n_neighs),                                    &
!                        neigh%fyro_bnd(nx_block, n_neighs), neigh%fymx_bnd(nx_block, n_neighs),                                    &
!                        neigh%fymy_bnd(nx_block, n_neighs), neigh%fymz_bnd(nx_block, n_neighs),                                    &
!                        neigh%fybx_bnd(nx_block, n_neighs), neigh%fyby_bnd(nx_block, n_neighs),                                    &
!                        neigh%fybz_bnd(nx_block, n_neighs), neigh%fyen_bnd(nx_block, n_neighs),                                    &
!                        neigh%fxpo_bnd(ny_block, n_neighs), neigh%fypo_bnd(nx_block, n_neighs))
!               neigh%var_allocate_flag = .true.
!               if (ini_value_save_flag .ne. 0) then
!                  allocate(neigh%ro0(nx_block, ny_block), neigh%mx0(nx_block, ny_block), neigh%my0(nx_block, ny_block),            &
!                           neigh%mz0(nx_block, ny_block), neigh%bx0(nx_block, ny_block), neigh%by0(nx_block, ny_block),            &
!                           neigh%bz0(nx_block, ny_block), neigh%en0(nx_block, ny_block), neigh%az0(nx_block, ny_block))
!               endif
!            endif
            n_neighs_exchange_send_x(neigh_cpu_id_p1) = n_neighs_exchange_send_x(neigh_cpu_id_p1) + 1
            neigh_index = n_neighs_exchange_send_x(neigh_cpu_id_p1)
!----------------------------------------------------------------------------------------------------------------------------------|
!           for the case n_neighs_exchange_send_x(neigh_cpu_id_p1) larger than the exchange_size_x
!----------------------------------------------------------------------------------------------------------------------------------|
            if (neigh_index .gt. exchange_size_x) then
               allocate(neighs_exchange_info_send_x_tmp(n_d_l + 1, exchange_size_x, cpu_number))
               allocate(neighs_exchange_info_recv_x_tmp(n_d_l + 1, exchange_size_x, cpu_number))
               exchange_size_x_tmp = exchange_size_x
               neighs_exchange_info_send_x_tmp = neighs_exchange_info_send_x
               neighs_exchange_info_recv_x_tmp = neighs_exchange_info_recv_x
               exchange_size_x = exchange_size_x + ini_block_x * ini_block_y
               deallocate(neighs_exchange_info_send_x)
               deallocate(neighs_exchange_info_recv_x)
               allocate(neighs_exchange_info_send_x(n_d_l + 1, exchange_size_x, cpu_number))
               allocate(neighs_exchange_info_recv_x(n_d_l + 1, exchange_size_x, cpu_number))
               neighs_exchange_info_send_x(:, 1 : exchange_size_x_tmp, :) = neighs_exchange_info_send_x_tmp
               neighs_exchange_info_recv_x(:, 1 : exchange_size_x_tmp, :) = neighs_exchange_info_recv_x_tmp
               deallocate(neighs_exchange_info_send_x_tmp)
               deallocate(neighs_exchange_info_recv_x_tmp)
            endif
            neighs_exchange_info_send_x(1 : n_d_l, neigh_index, neigh_cpu_id_p1) = reshape(current%id, (/ n_d_l /))
            neighs_exchange_info_send_x(n_d_l + 1, neigh_index, neigh_cpu_id_p1) = i_neigh
         endif

!----------------------------------------------------------------------------------------------------------------------------------|
!        collect information of neighbors for sending sharing block data in x (same levels)
!----------------------------------------------------------------------------------------------------------------------------------|
         if (current%nc .ne. 0 .and. neigh%nc .eq. 0) then
            child_send_flag = .false.
            if (i_neigh .eq. -1) i_block = 1
            if (i_neigh .eq. 1) i_block = ratio
            do j_block = 1, ratio
               child => current%child(i_block, j_block)%pblock
               child_cpu_id_p1 = child%cpu_id + 1
               if (child%cpu_id .ne. current%cpu_id .and. .not. child_send_flag(child_cpu_id_p1)) then
                  n_neighs_shareblock_send_x(child_cpu_id_p1) = n_neighs_shareblock_send_x(child_cpu_id_p1) + 1
                  neigh_index = n_neighs_shareblock_send_x(child_cpu_id_p1)
!----------------------------------------------------------------------------------------------------------------------------------|
!                 for the case n_neighs_shareblock_send_x(neigh_cpu_id_p1) larger than the shareblock_size_x
!----------------------------------------------------------------------------------------------------------------------------------|
                  if (neigh_index .gt. shareblock_size_x) then
                     allocate(neighs_shareblock_info_send_x_tmp(n_d_l + 1, shareblock_size_x, cpu_number))
                     allocate(neighs_shareblock_info_recv_x_tmp(n_d_l + 1, shareblock_size_x, cpu_number))
                     shareblock_size_x_tmp = shareblock_size_x
                     neighs_shareblock_info_send_x_tmp = neighs_shareblock_info_send_x
                     neighs_shareblock_info_recv_x_tmp = neighs_shareblock_info_recv_x
                     shareblock_size_x = shareblock_size_x + ini_block_x * ini_block_y
                     deallocate(neighs_shareblock_info_send_x)
                     deallocate(neighs_shareblock_info_recv_x)
                     allocate(neighs_shareblock_info_send_x(n_d_l + 1, shareblock_size_x, cpu_number))
                     allocate(neighs_shareblock_info_recv_x(n_d_l + 1, shareblock_size_x, cpu_number))
                     neighs_shareblock_info_send_x(:, 1 : shareblock_size_x_tmp, :) = neighs_shareblock_info_send_x_tmp
                     neighs_shareblock_info_recv_x(:, 1 : shareblock_size_x_tmp, :) = neighs_shareblock_info_recv_x_tmp
                     deallocate(neighs_shareblock_info_send_x_tmp)
                     deallocate(neighs_shareblock_info_recv_x_tmp)
                  endif
                  neighs_shareblock_info_send_x(1 : n_d_l, neigh_index, child_cpu_id_p1) = reshape(current%id, (/ n_d_l /))
                  neighs_shareblock_info_send_x(n_d_l + 1, neigh_index, child_cpu_id_p1) = i_neigh
                  child_send_flag(child_cpu_id_p1) = .true.
               endif
            enddo
         endif
      enddo

!----------------------------------------------------------------------------------------------------------------------------------|
!     statistics in y direction
!----------------------------------------------------------------------------------------------------------------------------------|
      i_neigh = 0
      do j_neigh = -1, 1, 2      !  skip current%neigh(0, 0)%pblock
         neigh => current%neigh(i_neigh, j_neigh)%pblock

!----------------------------------------------------------------------------------------------------------------------------------|
!        skip if neigh is physical boundary or inner physical boundary
!----------------------------------------------------------------------------------------------------------------------------------|
         if (.not. associated (neigh)) cycle
         if (neigh%lv .lt. 0) cycle

         neigh_cpu_id_p1 = neigh%cpu_id + 1

!----------------------------------------------------------------------------------------------------------------------------------|
!        collect information of neighbors for sending reflux data in y (different levels)
!----------------------------------------------------------------------------------------------------------------------------------|
         if (current%lv .gt. neigh%lv .and. neigh%cpu_id .ne. cpu_id) then
            n_neighs_reflux_send_y(neigh_cpu_id_p1) = n_neighs_reflux_send_y(neigh_cpu_id_p1) + 1
            neigh_index = n_neighs_reflux_send_y(neigh_cpu_id_p1)
!----------------------------------------------------------------------------------------------------------------------------------|
!           for the case n_neighs_reflux_send_y(neigh_cpu_id_p1) larger than the reflux_size_y
!----------------------------------------------------------------------------------------------------------------------------------|
            if (neigh_index .gt. reflux_size_y) then
               allocate(neighs_reflux_info_send_y_tmp(n_d_l + 1, reflux_size_y, cpu_number))
               allocate(neighs_reflux_info_recv_y_tmp(n_d_l + 1, reflux_size_y, cpu_number))
               reflux_size_y_tmp = reflux_size_y
               neighs_reflux_info_send_y_tmp = neighs_reflux_info_send_y
               neighs_reflux_info_recv_y_tmp = neighs_reflux_info_recv_y
               reflux_size_y = reflux_size_y + ini_block_x * ini_block_y
               deallocate(neighs_reflux_info_send_y)
               deallocate(neighs_reflux_info_recv_y)
               allocate(neighs_reflux_info_send_y(n_d_l + 1, reflux_size_y, cpu_number))
               allocate(neighs_reflux_info_recv_y(n_d_l + 1, reflux_size_y, cpu_number))
               neighs_reflux_info_send_y(:, 1 : reflux_size_y_tmp, :) = neighs_reflux_info_send_y_tmp
               neighs_reflux_info_recv_y(:, 1 : reflux_size_y_tmp, :) = neighs_reflux_info_recv_y_tmp
               deallocate(neighs_reflux_info_send_y_tmp)
               deallocate(neighs_reflux_info_recv_y_tmp)
            endif
            neighs_reflux_info_send_y(1 : n_d_l, neigh_index, neigh_cpu_id_p1) = reshape(current%id, (/ n_d_l /))
            neighs_reflux_info_send_y(n_d_l + 1, neigh_index, neigh_cpu_id_p1) = j_neigh
            cycle
         endif

!----------------------------------------------------------------------------------------------------------------------------------|
!        collect information of neighbors for sending boundary data in y (same levels)
!----------------------------------------------------------------------------------------------------------------------------------|
         if (neigh%cpu_id .ne. cpu_id) then
!            neigh%var_deallocate_flag = .false.
!            if (.not. neigh%var_allocate_flag) then
!               allocate(neigh%ro(nx_block, ny_block), neigh%mx(nx_block, ny_block), neigh%my(nx_block, ny_block),                  &
!                        neigh%mz(nx_block, ny_block), neigh%bx(nx_block, ny_block), neigh%by(nx_block, ny_block),                  &
!                        neigh%bz(nx_block, ny_block), neigh%en(nx_block, ny_block), neigh%gx(nx_block, ny_block),                  &
!                        neigh%gy(nx_block, ny_block), neigh%po(nx_block, ny_block), neigh%az(nx_block, ny_block))
!               allocate(neigh%fxro_bnd(ny_block, n_neighs), neigh%fxmx_bnd(ny_block, n_neighs),                                    &
!                        neigh%fxmy_bnd(ny_block, n_neighs), neigh%fxmz_bnd(ny_block, n_neighs),                                    &
!                        neigh%fxbx_bnd(ny_block, n_neighs), neigh%fxby_bnd(ny_block, n_neighs),                                    &
!                        neigh%fxbz_bnd(ny_block, n_neighs), neigh%fxen_bnd(ny_block, n_neighs),                                    &
!                        neigh%fyro_bnd(nx_block, n_neighs), neigh%fymx_bnd(nx_block, n_neighs),                                    &
!                        neigh%fymy_bnd(nx_block, n_neighs), neigh%fymz_bnd(nx_block, n_neighs),                                    &
!                        neigh%fybx_bnd(nx_block, n_neighs), neigh%fyby_bnd(nx_block, n_neighs),                                    &
!                        neigh%fybz_bnd(nx_block, n_neighs), neigh%fyen_bnd(nx_block, n_neighs),                                    &
!                        neigh%fxpo_bnd(ny_block, n_neighs), neigh%fypo_bnd(nx_block, n_neighs))
!               neigh%var_allocate_flag = .true.
!               if (ini_value_save_flag .ne. 0) then
!                  allocate(neigh%ro0(nx_block, ny_block), neigh%mx0(nx_block, ny_block), neigh%my0(nx_block, ny_block),            &
!                           neigh%mz0(nx_block, ny_block), neigh%bx0(nx_block, ny_block), neigh%by0(nx_block, ny_block),            &
!                           neigh%bz0(nx_block, ny_block), neigh%en0(nx_block, ny_block), neigh%az0(nx_block, ny_block))
!               endif
!            endif
            n_neighs_exchange_send_y(neigh_cpu_id_p1) = n_neighs_exchange_send_y(neigh_cpu_id_p1) + 1
            neigh_index = n_neighs_exchange_send_y(neigh_cpu_id_p1)
!----------------------------------------------------------------------------------------------------------------------------------|
!           for the case n_neighs_exchange_send_y(neigh_cpu_id_p1) larger than the exchange_size_y
!----------------------------------------------------------------------------------------------------------------------------------|
            if (neigh_index .gt. exchange_size_y) then
               allocate(neighs_exchange_info_send_y_tmp(n_d_l + 1, exchange_size_y, cpu_number))
               allocate(neighs_exchange_info_recv_y_tmp(n_d_l + 1, exchange_size_y, cpu_number))
               exchange_size_y_tmp = exchange_size_y
               neighs_exchange_info_send_y_tmp = neighs_exchange_info_send_y
               neighs_exchange_info_recv_y_tmp = neighs_exchange_info_recv_y
               exchange_size_y = exchange_size_y + ini_block_x * ini_block_y
               deallocate(neighs_exchange_info_send_y)
               deallocate(neighs_exchange_info_recv_y)
               allocate(neighs_exchange_info_send_y(n_d_l + 1, exchange_size_y, cpu_number))
               allocate(neighs_exchange_info_recv_y(n_d_l + 1, exchange_size_y, cpu_number))
               neighs_exchange_info_send_y(:, 1 : exchange_size_y_tmp, :) = neighs_exchange_info_send_y_tmp
               neighs_exchange_info_recv_y(:, 1 : exchange_size_y_tmp, :) = neighs_exchange_info_recv_y_tmp
               deallocate(neighs_exchange_info_send_y_tmp)
               deallocate(neighs_exchange_info_recv_y_tmp)
            endif
            neighs_exchange_info_send_y(1 : n_d_l, neigh_index, neigh_cpu_id_p1) = reshape(current%id, (/ n_d_l /))
            neighs_exchange_info_send_y(n_d_l + 1, neigh_index, neigh_cpu_id_p1) = j_neigh

!----------------------------------------------------------------------------------------------------------------------------------|
!           collect information of neighbors for fixing boundary data in y because of the shareblocks (same levels)
!----------------------------------------------------------------------------------------------------------------------------------|
            do i_neigh_x = -1, 1, 2
               neigh_x => current%neigh(i_neigh_x, 0)%pblock
               neigh_c => current%neigh(i_neigh_x, j_neigh)%pblock
               if (associated (neigh_x) .and. associated (neigh_c)) then
                  if (neigh_x%lv .eq. current%lv - 1 .and. neigh_c%lv .eq. current%lv) then
                     n_neighs_exchange_send_fix_y(neigh_cpu_id_p1) = n_neighs_exchange_send_fix_y(neigh_cpu_id_p1) + 1
                     neigh_index = n_neighs_exchange_send_fix_y(neigh_cpu_id_p1)
!----------------------------------------------------------------------------------------------------------------------------------|
!                    for the case n_neighs_exchange_send_fix_y(neigh_cpu_id_p1) larger than the exchange_size_fix_y
!----------------------------------------------------------------------------------------------------------------------------------|
                     if (neigh_index .gt. exchange_size_fix_y) then
                        allocate(neighs_exchange_info_send_fix_y_tmp(n_d_l + 1, exchange_size_fix_y, cpu_number))
                        allocate(neighs_exchange_info_recv_fix_y_tmp(n_d_l + 1, exchange_size_fix_y, cpu_number))
                        exchange_size_fix_y_tmp = exchange_size_fix_y
                        neighs_exchange_info_send_fix_y_tmp = neighs_exchange_info_send_fix_y
                        neighs_exchange_info_recv_fix_y_tmp = neighs_exchange_info_recv_fix_y
                        exchange_size_fix_y = exchange_size_fix_y + ini_block_x * ini_block_y
                        deallocate(neighs_exchange_info_send_fix_y)
                        deallocate(neighs_exchange_info_recv_fix_y)
                        allocate(neighs_exchange_info_send_fix_y(n_d_l + 1, exchange_size_fix_y, cpu_number))
                        allocate(neighs_exchange_info_recv_fix_y(n_d_l + 1, exchange_size_fix_y, cpu_number))
                        neighs_exchange_info_send_fix_y(:, 1 : exchange_size_fix_y_tmp, :) = neighs_exchange_info_send_fix_y_tmp
                        neighs_exchange_info_recv_fix_y(:, 1 : exchange_size_fix_y_tmp, :) = neighs_exchange_info_recv_fix_y_tmp
                        deallocate(neighs_exchange_info_send_fix_y_tmp)
                        deallocate(neighs_exchange_info_recv_fix_y_tmp)
                     endif
                     neighs_exchange_info_send_fix_y(1 : n_d_l, neigh_index, neigh_cpu_id_p1) = reshape(current%id, (/ n_d_l /))
                     neighs_exchange_info_send_fix_y(n_d_l + 1, neigh_index, neigh_cpu_id_p1) = j_neigh
                     exit
                  endif
               endif
            enddo
         endif

!----------------------------------------------------------------------------------------------------------------------------------|
!        collect information of neighbors for sending sharing block data in y (same levels)
!----------------------------------------------------------------------------------------------------------------------------------|
         if (current%nc .ne. 0 .and. neigh%nc .eq. 0) then
            child_send_flag = .false.
            if (j_neigh .eq. -1) j_block = 1
            if (j_neigh .eq. 1) j_block = ratio
            do i_block = 1, ratio
               child => current%child(i_block, j_block)%pblock
               child_cpu_id_p1 = child%cpu_id + 1
               if (child%cpu_id .ne. current%cpu_id .and. .not. child_send_flag(child_cpu_id_p1)) then
                  n_neighs_shareblock_send_y(child_cpu_id_p1) = n_neighs_shareblock_send_y(child_cpu_id_p1) + 1
                  neigh_index = n_neighs_shareblock_send_y(child_cpu_id_p1)
!----------------------------------------------------------------------------------------------------------------------------------|
!                 for the case n_neighs_shareblock_send_y(neigh_cpu_id_p1) larger than the shareblock_size_y
!----------------------------------------------------------------------------------------------------------------------------------|
                  if (neigh_index .gt. shareblock_size_y) then
                     allocate(neighs_shareblock_info_send_y_tmp(n_d_l + 1, shareblock_size_y, cpu_number))
                     allocate(neighs_shareblock_info_recv_y_tmp(n_d_l + 1, shareblock_size_y, cpu_number))
                     shareblock_size_y_tmp = shareblock_size_y
                     neighs_shareblock_info_send_y_tmp = neighs_shareblock_info_send_y
                     neighs_shareblock_info_recv_y_tmp = neighs_shareblock_info_recv_y
                     shareblock_size_y = shareblock_size_y + ini_block_x * ini_block_y
                     deallocate(neighs_shareblock_info_send_y)
                     deallocate(neighs_shareblock_info_recv_y)
                     allocate(neighs_shareblock_info_send_y(n_d_l + 1, shareblock_size_y, cpu_number))
                     allocate(neighs_shareblock_info_recv_y(n_d_l + 1, shareblock_size_y, cpu_number))
                     neighs_shareblock_info_send_y(:, 1 : shareblock_size_y_tmp, :) = neighs_shareblock_info_send_y_tmp
                     neighs_shareblock_info_recv_y(:, 1 : shareblock_size_y_tmp, :) = neighs_shareblock_info_recv_y_tmp
                     deallocate(neighs_shareblock_info_send_y_tmp)
                     deallocate(neighs_shareblock_info_recv_y_tmp)
                  endif
                  neighs_shareblock_info_send_y(1 : n_d_l, neigh_index, child_cpu_id_p1) = reshape(current%id, (/ n_d_l /))
                  neighs_shareblock_info_send_y(n_d_l + 1, neigh_index, child_cpu_id_p1) = j_neigh
                  child_send_flag(child_cpu_id_p1) = .true.
               endif
            enddo
         endif
      enddo

      current => current%next
   enddo

!!----------------------------------------------------------------------------------------------------------------------------------|
!!  deallocatethe memory which is unnecessary
!!----------------------------------------------------------------------------------------------------------------------------------|
!   current => base%framework_next
!   do while (current%lv .ne. 0)
!      if (current%var_deallocate_flag) then
!         if (current%var_allocate_flag) then
!            deallocate(current%ro, current%mx, current%my, current%mz, current%bx, current%by, current%bz, current%en,             &
!                       current%gx, current%gy, current%po, current%az)
!            deallocate(current%fxro_bnd, current%fxmx_bnd, current%fxmy_bnd, current%fxmz_bnd,                                     &
!                       current%fxbx_bnd, current%fxby_bnd, current%fxbz_bnd, current%fxen_bnd,                                     &
!                       current%fyro_bnd, current%fymx_bnd, current%fymy_bnd, current%fymz_bnd,                                     &
!                       current%fybx_bnd, current%fyby_bnd, current%fybz_bnd, current%fyen_bnd,                                     &
!                       current%fxpo_bnd, current%fypo_bnd)
!            current%var_allocate_flag = .false.
!            if (ini_value_save_flag .ne. 0) then
!               deallocate(current%ro0, current%mx0, current%my0, current%mz0, current%bx0, current%by0, current%bz0, current%en0,  &
!                  current%az0)
!            endif
!         endif
!         current%var_deallocate_flag = .false.
!      endif
!      current => current%framework_next
!   enddo

!----------------------------------------------------------------------------------------------------------------------------------|
!  collect the information from other cpu
!----------------------------------------------------------------------------------------------------------------------------------|
   call mpi_allgather (n_neighs_reflux_send_x, cpu_number, mpi_integer4,                                                           &
      n_neighs_reflux_sendrecv_x, cpu_number, mpi_integer4,                                                                        &
      mpi_comm_world, error)
   call mpi_allgather (n_neighs_reflux_send_y, cpu_number, mpi_integer4,                                                           &
      n_neighs_reflux_sendrecv_y, cpu_number, mpi_integer4,                                                                        &
      mpi_comm_world, error)
   call mpi_allgather (n_neighs_shareblock_send_x, cpu_number, mpi_integer4,                                                       &
      n_neighs_shareblock_sendrecv_x, cpu_number, mpi_integer4,                                                                    &
      mpi_comm_world, error)
   call mpi_allgather (n_neighs_shareblock_send_y, cpu_number, mpi_integer4,                                                       &
      n_neighs_shareblock_sendrecv_y, cpu_number, mpi_integer4,                                                                    &
      mpi_comm_world, error)
   call mpi_allgather (n_neighs_exchange_send_x, cpu_number, mpi_integer4,                                                         &
      n_neighs_exchange_sendrecv_x, cpu_number, mpi_integer4,                                                                      &
      mpi_comm_world, error)
   call mpi_allgather (n_neighs_exchange_send_y, cpu_number, mpi_integer4,                                                         &
      n_neighs_exchange_sendrecv_y, cpu_number, mpi_integer4,                                                                      &
      mpi_comm_world, error)
   call mpi_allgather (n_neighs_exchange_send_fix_y, cpu_number, mpi_integer4,                                                     &
      n_neighs_exchange_sendrecv_fix_y, cpu_number, mpi_integer4,                                                                  &
      mpi_comm_world, error)

!----------------------------------------------------------------------------------------------------------------------------------|
!  resize the buffer array for reflux, exchange and shareblock
!----------------------------------------------------------------------------------------------------------------------------------|
   reflux_size_send_x = max(sum(n_neighs_reflux_sendrecv_x(:, cpu_id_p1)), 1)
   reflux_size_recv_x = max(sum(n_neighs_reflux_sendrecv_x(cpu_id_p1, :)), 1)
   reflux_size_send_y = max(sum(n_neighs_reflux_sendrecv_y(:, cpu_id_p1)), 1)
   reflux_size_recv_y = max(sum(n_neighs_reflux_sendrecv_y(cpu_id_p1, :)), 1)
   shareblock_size_send_x = max(sum(n_neighs_shareblock_sendrecv_x(:, cpu_id_p1)), 1)
   shareblock_size_recv_x = max(sum(n_neighs_shareblock_sendrecv_x(cpu_id_p1, :)), 1)
   shareblock_size_send_y = max(sum(n_neighs_shareblock_sendrecv_y(:, cpu_id_p1)), 1)
   shareblock_size_recv_y = max(sum(n_neighs_shareblock_sendrecv_y(cpu_id_p1, :)), 1)
   exchange_size_send_x = max(sum(n_neighs_exchange_sendrecv_x(:, cpu_id_p1)), 1)
   exchange_size_recv_x = max(sum(n_neighs_exchange_sendrecv_x(cpu_id_p1, :)), 1)
   exchange_size_send_y = max(sum(n_neighs_exchange_sendrecv_y(:, cpu_id_p1)), 1)
   exchange_size_recv_y = max(sum(n_neighs_exchange_sendrecv_y(cpu_id_p1, :)), 1)

   allocate(neighs_reflux_send_x(sys, ny_no_bnd, reflux_size_send_x))
   allocate(neighs_reflux_send_y(sys, nx_no_bnd, reflux_size_send_y))
   allocate(neighs_reflux_recv_x(sys, ny_no_bnd, reflux_size_recv_x))
   allocate(neighs_reflux_recv_y(sys, nx_no_bnd, reflux_size_recv_y))
   allocate(neighs_shareblock_send_x(sys + 2, ng + 1, ny_block, shareblock_size_send_x))
   allocate(neighs_shareblock_send_y(sys + 2, nx_block, ng + 1, shareblock_size_send_y))
   allocate(neighs_shareblock_recv_x(sys + 2, ng + 1, ny_block, shareblock_size_recv_x))
   allocate(neighs_shareblock_recv_y(sys + 2, nx_block, ng + 1, shareblock_size_recv_y))
   allocate(neighs_exchange_send_x(sys + 2, ng, ny_no_bnd, exchange_size_send_x))
   allocate(neighs_exchange_send_y(sys + 2, nx_block, ng, exchange_size_send_y))
   allocate(neighs_exchange_recv_x(sys + 2, ng, ny_no_bnd, exchange_size_recv_x))
   allocate(neighs_exchange_recv_y(sys + 2, nx_block, ng, exchange_size_recv_y))
   allocate(neighs_shareblock_send_x_hc(1, ng + 1, ny_block, shareblock_size_send_x))
   allocate(neighs_shareblock_send_y_hc(1, nx_block, ng + 1, shareblock_size_send_y))
   allocate(neighs_shareblock_recv_x_hc(1, ng + 1, ny_block, shareblock_size_recv_x))
   allocate(neighs_shareblock_recv_y_hc(1, nx_block, ng + 1, shareblock_size_recv_y))
   allocate(neighs_exchange_send_x_hc(1, ng, ny_no_bnd, exchange_size_send_x))
   allocate(neighs_exchange_send_y_hc(1, nx_block, ng, exchange_size_send_y))
   allocate(neighs_exchange_recv_x_hc(1, ng, ny_no_bnd, exchange_size_recv_x))
   allocate(neighs_exchange_recv_y_hc(1, nx_block, ng, exchange_size_recv_y))

   if (max(maxval(n_neighs_reflux_sendrecv_x(cpu_id_p1, :)),                                                                       &
           maxval(n_neighs_reflux_sendrecv_x(:, cpu_id_p1))) .ne. reflux_size_x) then
      allocate(neighs_reflux_info_send_x_tmp(n_d_l + 1, reflux_size_x, cpu_number))
      allocate(neighs_reflux_info_recv_x_tmp(n_d_l + 1, reflux_size_x, cpu_number))
      reflux_size_x_tmp = min(max(maxval(n_neighs_reflux_sendrecv_x(cpu_id_p1, :)),                                                &
                                  maxval(n_neighs_reflux_sendrecv_x(:, cpu_id_p1))) + 1, reflux_size_x)
      reflux_size_x = max(maxval(n_neighs_reflux_sendrecv_x(cpu_id_p1, :)),                                                        &
                          maxval(n_neighs_reflux_sendrecv_x(:, cpu_id_p1))) + 1   ! avoid reflux_size_x = 0
      neighs_reflux_info_send_x_tmp = neighs_reflux_info_send_x
      neighs_reflux_info_recv_x_tmp = neighs_reflux_info_recv_x
      deallocate(neighs_reflux_info_send_x)
      deallocate(neighs_reflux_info_recv_x)
      allocate(neighs_reflux_info_send_x(n_d_l + 1, reflux_size_x, cpu_number))
      allocate(neighs_reflux_info_recv_x(n_d_l + 1, reflux_size_x, cpu_number))
      neighs_reflux_info_send_x(:, 1 : reflux_size_x_tmp, :) =                                                                     &
         neighs_reflux_info_send_x_tmp(:, 1 : reflux_size_x_tmp, :)
      neighs_reflux_info_recv_x(:, 1 : reflux_size_x_tmp, :) =                                                                     &
         neighs_reflux_info_recv_x_tmp(:, 1 : reflux_size_x_tmp, :)
      deallocate(neighs_reflux_info_send_x_tmp)
      deallocate(neighs_reflux_info_recv_x_tmp)
   endif

   if (max(maxval(n_neighs_reflux_sendrecv_y(cpu_id_p1, :)),                                                                       &
           maxval(n_neighs_reflux_sendrecv_y(:, cpu_id_p1))) .ne. reflux_size_y) then
      allocate(neighs_reflux_info_send_y_tmp(n_d_l + 1, reflux_size_y, cpu_number))
      allocate(neighs_reflux_info_recv_y_tmp(n_d_l + 1, reflux_size_y, cpu_number))
      reflux_size_y_tmp = min(max(maxval(n_neighs_reflux_sendrecv_y(cpu_id_p1, :)),                                                &
                                  maxval(n_neighs_reflux_sendrecv_y(:, cpu_id_p1))) + 1, reflux_size_y)
      reflux_size_y = max(maxval(n_neighs_reflux_sendrecv_y(cpu_id_p1, :)),                                                        &
                          maxval(n_neighs_reflux_sendrecv_y(:, cpu_id_p1))) + 1
      neighs_reflux_info_send_y_tmp = neighs_reflux_info_send_y
      neighs_reflux_info_recv_y_tmp = neighs_reflux_info_recv_y
      deallocate(neighs_reflux_info_send_y)
      deallocate(neighs_reflux_info_recv_y)
      allocate(neighs_reflux_info_send_y(n_d_l + 1, reflux_size_y, cpu_number))
      allocate(neighs_reflux_info_recv_y(n_d_l + 1, reflux_size_y, cpu_number))
      neighs_reflux_info_send_y(:, 1 : reflux_size_y_tmp, :) =                                                                     &
         neighs_reflux_info_send_y_tmp(:, 1 : reflux_size_y_tmp, :)
      neighs_reflux_info_recv_y(:, 1 : reflux_size_y_tmp, :) =                                                                     &
         neighs_reflux_info_recv_y_tmp(:, 1 : reflux_size_y_tmp, :)
      deallocate(neighs_reflux_info_send_y_tmp)
      deallocate(neighs_reflux_info_recv_y_tmp)
   endif

   if (max(maxval(n_neighs_exchange_sendrecv_x(cpu_id_p1, :)),                                                                     &
           maxval(n_neighs_exchange_sendrecv_x(:, cpu_id_p1))) .ne. exchange_size_x) then
      allocate(neighs_exchange_info_send_x_tmp(n_d_l + 1, exchange_size_x, cpu_number))
      allocate(neighs_exchange_info_recv_x_tmp(n_d_l + 1, exchange_size_x, cpu_number))
      exchange_size_x_tmp = min(max(maxval(n_neighs_exchange_sendrecv_x(cpu_id_p1, :)),                                            &
                                    maxval(n_neighs_exchange_sendrecv_x(:, cpu_id_p1))) + 1, exchange_size_x)
      exchange_size_x = max(maxval(n_neighs_exchange_sendrecv_x(cpu_id_p1, :)),                                                    &
                            maxval(n_neighs_exchange_sendrecv_x(:, cpu_id_p1))) + 1
      neighs_exchange_info_send_x_tmp = neighs_exchange_info_send_x
      neighs_exchange_info_recv_x_tmp = neighs_exchange_info_recv_x
      deallocate(neighs_exchange_info_send_x)
      deallocate(neighs_exchange_info_recv_x)
      allocate(neighs_exchange_info_send_x(n_d_l + 1, exchange_size_x, cpu_number))
      allocate(neighs_exchange_info_recv_x(n_d_l + 1, exchange_size_x, cpu_number))
      neighs_exchange_info_send_x(:, 1 : exchange_size_x_tmp, :) =                                                                 &
         neighs_exchange_info_send_x_tmp(:, 1 : exchange_size_x_tmp, :)
      neighs_exchange_info_recv_x(:, 1 : exchange_size_x_tmp, :) =                                                                 &
         neighs_exchange_info_recv_x_tmp(:, 1 : exchange_size_x_tmp, :)
      deallocate(neighs_exchange_info_send_x_tmp)
      deallocate(neighs_exchange_info_recv_x_tmp)
   endif

   if (max(maxval(n_neighs_exchange_sendrecv_y(cpu_id_p1, :)),                                                                     &
           maxval(n_neighs_exchange_sendrecv_y(:, cpu_id_p1))) .ne. exchange_size_y) then
      allocate(neighs_exchange_info_send_y_tmp(n_d_l + 1, exchange_size_y, cpu_number))
      allocate(neighs_exchange_info_recv_y_tmp(n_d_l + 1, exchange_size_y, cpu_number))
      exchange_size_y_tmp = min(max(maxval(n_neighs_exchange_sendrecv_y(cpu_id_p1, :)),                                            &
                                    maxval(n_neighs_exchange_sendrecv_y(:, cpu_id_p1))) + 1, exchange_size_y)
      exchange_size_y = max(maxval(n_neighs_exchange_sendrecv_y(cpu_id_p1, :)),                                                    &
                            maxval(n_neighs_exchange_sendrecv_y(:, cpu_id_p1))) + 1
      neighs_exchange_info_send_y_tmp = neighs_exchange_info_send_y
      neighs_exchange_info_recv_y_tmp = neighs_exchange_info_recv_y
      deallocate(neighs_exchange_info_send_y)
      deallocate(neighs_exchange_info_recv_y)
      allocate(neighs_exchange_info_send_y(n_d_l + 1, exchange_size_y, cpu_number))
      allocate(neighs_exchange_info_recv_y(n_d_l + 1, exchange_size_y, cpu_number))
      neighs_exchange_info_send_y(:, 1 : exchange_size_y_tmp, :) =                                                                 &
         neighs_exchange_info_send_y_tmp(:, 1 : exchange_size_y_tmp, :)
      neighs_exchange_info_recv_y(:, 1 : exchange_size_y_tmp, :) =                                                                 &
         neighs_exchange_info_recv_y_tmp(:, 1 : exchange_size_y_tmp, :)
      deallocate(neighs_exchange_info_send_y_tmp)
      deallocate(neighs_exchange_info_recv_y_tmp)
   endif

   if (max(maxval(n_neighs_shareblock_sendrecv_x(cpu_id_p1, :)),                                                                   &
           maxval(n_neighs_shareblock_sendrecv_x(:, cpu_id_p1))) .ne. shareblock_size_x) then
      allocate(neighs_shareblock_info_send_x_tmp(n_d_l + 1, shareblock_size_x, cpu_number))
      allocate(neighs_shareblock_info_recv_x_tmp(n_d_l + 1, shareblock_size_x, cpu_number))
      shareblock_size_x_tmp = min(max(maxval(n_neighs_shareblock_sendrecv_x(cpu_id_p1, :)),                                        &
                                      maxval(n_neighs_shareblock_sendrecv_x(:, cpu_id_p1))) + 1, shareblock_size_x)
      shareblock_size_x = max(maxval(n_neighs_shareblock_sendrecv_x(cpu_id_p1, :)),                                                &
                              maxval(n_neighs_shareblock_sendrecv_x(:, cpu_id_p1))) + 1
      neighs_shareblock_info_send_x_tmp = neighs_shareblock_info_send_x
      neighs_shareblock_info_recv_x_tmp = neighs_shareblock_info_recv_x
      deallocate(neighs_shareblock_info_send_x)
      deallocate(neighs_shareblock_info_recv_x)
      allocate(neighs_shareblock_info_send_x(n_d_l + 1, shareblock_size_x, cpu_number))
      allocate(neighs_shareblock_info_recv_x(n_d_l + 1, shareblock_size_x, cpu_number))
      neighs_shareblock_info_send_x(:, 1 : shareblock_size_x_tmp, :) =                                                             &
         neighs_shareblock_info_send_x_tmp(:, 1 : shareblock_size_x_tmp, :)
      neighs_shareblock_info_recv_x(:, 1 : shareblock_size_x_tmp, :) =                                                             &
         neighs_shareblock_info_recv_x_tmp(:, 1 : shareblock_size_x_tmp, :)
      deallocate(neighs_shareblock_info_send_x_tmp)
      deallocate(neighs_shareblock_info_recv_x_tmp)
   endif

   if (max(maxval(n_neighs_shareblock_sendrecv_y(cpu_id_p1, :)),                                                                   &
           maxval(n_neighs_shareblock_sendrecv_y(:, cpu_id_p1))) .ne. shareblock_size_y) then
      allocate(neighs_shareblock_info_send_y_tmp(n_d_l + 1, shareblock_size_y, cpu_number))
      allocate(neighs_shareblock_info_recv_y_tmp(n_d_l + 1, shareblock_size_y, cpu_number))
      shareblock_size_y_tmp = min(max(maxval(n_neighs_shareblock_sendrecv_y(cpu_id_p1, :)),                                        &
                                      maxval(n_neighs_shareblock_sendrecv_y(:, cpu_id_p1))) + 1, shareblock_size_y)
      shareblock_size_y = max(maxval(n_neighs_shareblock_sendrecv_y(cpu_id_p1, :)),                                                &
                              maxval(n_neighs_shareblock_sendrecv_y(:, cpu_id_p1))) + 1
      neighs_shareblock_info_send_y_tmp = neighs_shareblock_info_send_y
      neighs_shareblock_info_recv_y_tmp = neighs_shareblock_info_recv_y
      deallocate(neighs_shareblock_info_send_y)
      deallocate(neighs_shareblock_info_recv_y)
      allocate(neighs_shareblock_info_send_y(n_d_l + 1, shareblock_size_y, cpu_number))
      allocate(neighs_shareblock_info_recv_y(n_d_l + 1, shareblock_size_y, cpu_number))
      neighs_shareblock_info_send_y(:, 1 : shareblock_size_y_tmp, :) =                                                             &
         neighs_shareblock_info_send_y_tmp(:, 1 : shareblock_size_y_tmp, :)
      neighs_shareblock_info_recv_y(:, 1 : shareblock_size_y_tmp, :) =                                                             &
         neighs_shareblock_info_recv_y_tmp(:, 1 : shareblock_size_y_tmp, :)
      deallocate(neighs_shareblock_info_send_y_tmp)
      deallocate(neighs_shareblock_info_recv_y_tmp)
   endif

   if (max(maxval(n_neighs_exchange_sendrecv_fix_y(cpu_id_p1, :)),                                                                 &
           maxval(n_neighs_exchange_sendrecv_fix_y(:, cpu_id_p1))) .ne. exchange_size_fix_y) then
      allocate(neighs_exchange_info_send_fix_y_tmp(n_d_l + 1, exchange_size_fix_y, cpu_number))
      allocate(neighs_exchange_info_recv_fix_y_tmp(n_d_l + 1, exchange_size_fix_y, cpu_number))
      exchange_size_fix_y_tmp = min(max(maxval(n_neighs_exchange_sendrecv_fix_y(cpu_id_p1, :)),                                    &
                                        maxval(n_neighs_exchange_sendrecv_fix_y(:, cpu_id_p1))) + 1, exchange_size_fix_y)
      exchange_size_fix_y = max(maxval(n_neighs_exchange_sendrecv_fix_y(cpu_id_p1, :)),                                            &
                                maxval(n_neighs_exchange_sendrecv_fix_y(:, cpu_id_p1))) + 1
      neighs_exchange_info_send_fix_y_tmp = neighs_exchange_info_send_fix_y
      neighs_exchange_info_recv_fix_y_tmp = neighs_exchange_info_recv_fix_y
      deallocate(neighs_exchange_info_send_fix_y)
      deallocate(neighs_exchange_info_recv_fix_y)
      allocate(neighs_exchange_info_send_fix_y(n_d_l + 1, exchange_size_fix_y, cpu_number))
      allocate(neighs_exchange_info_recv_fix_y(n_d_l + 1, exchange_size_fix_y, cpu_number))
      neighs_exchange_info_send_fix_y(:, 1 : exchange_size_fix_y_tmp, :) =                                                         &
         neighs_exchange_info_send_fix_y_tmp(:, 1 : exchange_size_fix_y_tmp, :)
      neighs_exchange_info_recv_fix_y(:, 1 : exchange_size_fix_y_tmp, :) =                                                         &
         neighs_exchange_info_recv_fix_y_tmp(:, 1 : exchange_size_fix_y_tmp, :)
      deallocate(neighs_exchange_info_send_fix_y_tmp)
      deallocate(neighs_exchange_info_recv_fix_y_tmp)
   endif

!----------------------------------------------------------------------------------------------------------------------------------|
   return
end subroutine neigh_statistics
